package ch.unisi.inf.pfii.teamwhite.risk.graphic.gameFrame;

/**
 * 
 * @author Matteo Bellan: bellanm@lu.unisi.ch
 * @author Andrea Michelotti: micheloa@lu.unisi.ch
 * @author Ranganathan Ramasubramanian: ramasubr@lu.unisi.ch@lu.unisi.ch
 *
 */

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;

import ch.unisi.inf.pfii.teamwhite.risk.core.Game;
import ch.unisi.inf.pfii.teamwhite.risk.core.GameListener;
import ch.unisi.inf.pfii.teamwhite.risk.core.Planet;
import ch.unisi.inf.pfii.teamwhite.risk.core.io.CoordinatesReader;
import ch.unisi.inf.pfii.teamwhite.risk.core.player.Ai;
import ch.unisi.inf.pfii.teamwhite.risk.core.player.AiListener;
import ch.unisi.inf.pfii.teamwhite.risk.core.player.Human;
import ch.unisi.inf.pfii.teamwhite.risk.core.player.HumanListener;
import ch.unisi.inf.pfii.teamwhite.risk.core.player.Player;
import ch.unisi.inf.pfii.teamwhite.risk.graphic.gameFrame.dialogs.PlanetNameDialog;
import ch.unisi.inf.pfii.teamwhite.risk.graphic.gameFrame.drawers.DrawerListener;
import ch.unisi.inf.pfii.teamwhite.risk.graphic.gameFrame.drawers.GalaxyDrawer;
import ch.unisi.inf.pfii.teamwhite.risk.graphic.gameFrame.drawers.PlanetDrawer;
import ch.unisi.inf.pfii.teamwhite.risk.graphic.menuFrame.MenuFrame;
import ch.unisi.inf.pfii.teamwhite.risk.sound.SoundEngine;
import ch.unisi.inf.pfii.teamwhite.risk.sound.SoundInGame;

public class GameFrame extends JFrame{

	private Game game;
	
	private Container contentPane;
	private JPanel imagePanel;
	private JSlider numberOfShipsSlider;
	private JPanel playerInfos;
	private JPanel southPanel;
	private SoundInGame soundInGame;
	
	private String map;
	private String coordinates;
	private Planet selectedPlanet;
	private Planet originPlanet;
	private boolean duringGame;
	private  boolean soundEnabled;
	private String building;
	private int shipsToMove;

	private CoordinatesReader coordinatesReader;
	private GalaxyDrawer galaxyDrawer;
	private PlanetDrawer shipsDrawer;
	
	
	public GameFrame(final Game game, final String map, final boolean sound) {
		this.game = game;
		
		game.initialSetter(game.getPlayers().get(0), map);
		
		soundInGame = new SoundInGame(game, this);
		playerInfos = new PlayerInfoPanel(game);
		southPanel = new SouthPanel(game, selectedPlanet, imagePanel, this);
		
		this.map = map;
		coordinates = map + "XY.txt";
		selectedPlanet = null;
		originPlanet = null;
		duringGame = false;
		soundEnabled = sound;
		building = null;
		shipsToMove = 1;
		
		coordinatesReader = new CoordinatesReader(coordinates);
		galaxyDrawer = new GalaxyDrawer(game, this);
		galaxyDrawer.addDrawerListener(new DrawerListener(){
			public void packRequired() {
				shipsDrawer = new PlanetDrawer(game, coordinates);
				shipsDrawer.clearShips(imagePanel);
				shipsDrawer.drawShips(imagePanel);
				refreshMap();
				pack();
			}	
		});
		shipsDrawer = new PlanetDrawer(game, coordinates);
		
		contentPane = getContentPane();
		contentPane.setLayout(new BorderLayout());
		contentPane.add(playerInfos, BorderLayout.NORTH);
		makeCenter();
		contentPane.add(imagePanel, BorderLayout.CENTER);
		contentPane.add(southPanel, BorderLayout.SOUTH);
		
		playerListeners();
		gameListeners();
		
		setTitle("WARSHIP");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(1024, 768);
		setResizable(false);
		setLocationRelativeTo(null);
		setVisible(true); 
		pack();
	}
	
//	This method creates the player listeners
	private void playerListeners(){
		for(final Player player : game.getPlayers()){
			if(!duringGame){
			if(player.getType().equals("Human")){
				((Human) player).addHumanListener(new HumanListener(){
					
					public void planetAssigned() {
						if(player.getTerritory().size() == 1){
						}else if(game.getPlayers().indexOf(player) == game.getPlayers().size() - 1){
							duringGame = true;
							player.setDuringAssignment(false);
							game.nextPlayer();
						}else{
							player.setDuringAssignment(false);
							game.nextPlayer();
						}
						refreshPlayer();
						refreshMap();
						pack();
					}
					public void planetNotAvailable(){
						JOptionPane.showMessageDialog(contentPane, "Planet Not Available!");
					}
					
					public void planetChangement() {
						contentPane.remove(southPanel);
						selectedPlanet = ((Human)game.getCurrentPlayer()).getSelectedPlanet();
						southPanel = new SouthPanel(game, selectedPlanet, imagePanel, GameFrame.this);
						contentPane.add(southPanel, BorderLayout.SOUTH);
						pack();
					}
					
					public void shipChangement(){
						shipsDrawer = new PlanetDrawer(game, coordinates);
						shipsDrawer.clearShips(imagePanel);
						shipsDrawer.drawShips(imagePanel);
						refreshMap();
						pack();
					}
					
					public void moneyChangement(){
						contentPane.remove(playerInfos);
						playerInfos = new PlayerInfoPanel(game);
						contentPane.add(playerInfos, BorderLayout.NORTH);
						pack();
					}
					
					public void turnFinished(){
						nextMethod();
					}
					
					public void conqueredPlanet(final Planet planet){
						new PlanetNameDialog(game, GameFrame.this, planet);
						refreshPlayer();
						refreshMap();
						pack();
					}
					public void attack() {
					}
					public void moved() {
					}
					public void defensiveShield() {
					}
					public void slaveryCamp() {	
					}
					public void taxCenter() {	
					}
					public void eldestCouncil() {
					}
					
				});
			}else{
				((Ai)player).addAiListener(new AiListener(){
					public void turnFinished(){
						((Ai)player).stopTimers();
						contentPane.remove(playerInfos);
						playerInfos = new PlayerInfoPanel(game);
						contentPane.add(playerInfos, BorderLayout.NORTH);
						refreshMap();
						pack();
						nextMethod();
					}

					public void aiStep() {
						contentPane.remove(playerInfos);
						playerInfos = new PlayerInfoPanel(game);
						contentPane.add(playerInfos, BorderLayout.NORTH);
						refreshMap();
						pack();
					}
				});
				
				if(game.getPlayers().indexOf(player) == game.getPlayers().size() - 1){
					duringGame = true;
				}
				((Ai)player).assignPlanets(game.getGalaxy().getPlanets());
				player.setDuringAssignment(false);
				game.nextPlayer();
				refreshPlayer();
			}
		}else{	
		}
		}
	}

//	This method creates the player listeners
	private void gameListeners(){
		game.addGameListener(new GameListener(){
			
			public void playerLoose(Player player) {
				if(duringGame){
					JOptionPane.showMessageDialog(contentPane, player.getName() + ", you loose!");
				}
			}
			
			public void playerWon(Player player) {
				if(duringGame){
					JOptionPane.showMessageDialog(contentPane, player.getName() + ", you are the winner!");
					System.exit(0);
				}
			}
		});
	}
	
//	This method refresh the map removing the entire image and repainted it
	private void refreshMap(){
		contentPane.remove(imagePanel);
		makeCenter();
		contentPane.add(imagePanel, BorderLayout.CENTER);
	}
	
//	This method refresh the player panel, repainted it
	private void refreshPlayer() {
		contentPane.remove(playerInfos);
		playerInfos = new PlayerInfoPanel(game);
		contentPane.add(playerInfos, BorderLayout.NORTH);
	}
	
//	This method redraws all the info about the planets on the image panel
	private void drawMap(JPanel imagePanel) {
		for (String line : coordinatesReader.fileReader()) {
			String[] lineSplitted = line.split(" ");
			galaxyDrawer.drawGalaxy(lineSplitted, imagePanel);
		}
		shipsDrawer.drawShips(imagePanel);
	}
	
//	This method creates the image panel where the game runs
	private void makeCenter(){
		
		final JPanel imagePanel = new JPanel();
		imagePanel.setLayout(null);
		imagePanel.setPreferredSize(new Dimension(1010, 722));
		
		drawMap(imagePanel);
		
		String imageFile = "maps/" + map + ".png";
		
		ImageIcon image = new ImageIcon(getClass().getResource(imageFile));
		final JLabel imageLabel = new JLabel(image);
		imageLabel.setLayout(null);
		imageLabel.setBounds(0, 0, 1010, 722);
		imagePanel.add(imageLabel);
		
		this.imagePanel = imagePanel;
	}
	
//	This method creates the button next which invoke the next method which ends the turn of a player and switch to the next one
	public Component makeNext(){
		JButton next = new JButton("NEXT");
		next.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				new SoundEngine("next.wav", soundIsEnabled(), false);
				nextMethod();
			}
		});
		
		return next;
	}	
	
//	This method checks the player states, switch to the next player and refresh the graphic
	private void nextMethod(){
		game.checkPlayerState();
		if(game.getCurrentPlayer().getType().equals("Human")){
			((Human)game.getCurrentPlayer()).setSelectedPlanet(null);
		}
		game.nextPlayer();
		game.getCurrentPlayer().play(game.getCurrentPlayer().getTerritory(), "", 0);
		
		refreshPlayer();
		refreshMap();

		contentPane.remove(southPanel);
		southPanel = new SouthPanel(game, selectedPlanet, imagePanel, GameFrame.this);
		contentPane.add(southPanel, BorderLayout.SOUTH);
		
		pack();
	}
	
	public boolean soundIsEnabled(){
		return soundEnabled;
	}
	
	public Planet getSelectedPlanet() {
		return selectedPlanet;
	}
}